/*
	Copyright (c) 2010 <copyright holders>
	This source code is licensed under The MIT License,
	see the file LICENSE for details.
	*/

#include <OGRE/OgreErrorDialog.h>
#include <string>

#include "Game.hpp"
#include "MessageRegisters.hpp"
#include "BundleInfo.hpp"
#include "NetDefs.hpp"
#include "gen/netmsg.pb.h"
#include "gen/savemsg.pb.h"

/**
    @mainpage Herein lies the source code documentation of the spelprog2 programming project.
    */

#ifdef NDEBUG
#    ifdef __APPLE__
#        define PLUGIN_FILE "Contents/Resources/scripts/plugins_mac.cfg"
#    else
#        define PLUGIN_FILE "scripts/plugins.cfg"
#    endif
#    define RESOURCE_FILE "scripts/resources.cfg"
#else
#    ifdef __APPLE__
#        define PLUGIN_FILE "Contents/Resources/scripts/plugins_mac_d.cfg"
#    else
#        define PLUGIN_FILE "scripts/plugins_d.cfg"
#    endif
#    define RESOURCE_FILE "scripts/resources_d.cfg"
#endif

enum StartMode {
    NORMAL,
    HOST,
    JOIN,
    DEDICATED_HOST //TODO: don't use Game class for this
};

namespace spelprog2 {
    LogStream gamelog("Game.log");
    namespace net {
        LogStream netlog;
    };
};

static StartMode getStartMode(char * argv[]) {
    //this is for now done via a very crude method, we'll see if we have time to implement
    //proper command line option passing

    StartMode mode = NORMAL;
    for (char ** it = argv; *it != NULL; ++it) {
        std::string cmdArg(*it);
        if (cmdArg.compare("--host") == 0) {
            mode = HOST;
            break;
        }
        else if (cmdArg.compare("--join") == 0) {
            mode = JOIN;
            break;
        }
    }

    return mode;
}

static void registerNetMessages()
{
    using namespace spelprog2;
    MessageTypeRegistry & reg = MessageTypeRegistry::getInstance();

    //alphabetic order
    reg.registerMsg<netmsg::AttackWithSquad>();
    reg.registerMsg<netmsg::ChangeFormation>();
    reg.registerMsg<netmsg::ChatMessage>();
    reg.registerMsg<netmsg::FrameUpdate>();
    reg.registerMsg<netmsg::LoginReply>();
    reg.registerMsg<netmsg::LoginRequest>();
    reg.registerMsg<netmsg::MoveSquad>();
    reg.registerMsg<netmsg::ServerVarChange>();
    reg.registerMsg<netmsg::StartGame>();
    reg.registerMsg<netmsg::StopSquad>();
    reg.registerMsg<netmsg::UserChange>();
    reg.registerMsg<savemsg::ReplayFileHeader>();
}

// main function ========================================98======================

int main(int argc, char * argv[]) {
    using namespace spelprog2;

    MessageTypeRegistry::getInstance().registerErrorMsg<auxmsg::ErrorMessage>();
    registerNetMessages();
    MessageTypeRegistry::getInstance().lock();

    //decide if A) to start server, b) connect with client, or C) just start game normally
    StartMode startMode = getStartMode(argv);

    if (startMode == NORMAL || startMode == JOIN || startMode == HOST) {
	    //start graphical game; catch all Ogre exceptions
	    try {
		    Game game(getBundlePath(PLUGIN_FILE));
            game.locateResources(getBundlePath(RESOURCE_DEVIATION) + RESOURCE_FILE);

            if (startMode == HOST) {
                game.setAsServer("Goat of the goats", "", 5555);
            }
            else if (startMode == JOIN) {
                game.setAsClient("Pig of the pigs", "", "localhost", 5555);
            }
            else {
                game.setAsLocal();
            }

            game.run();
	    }
	    catch (Ogre::Exception & e) {
		    //display Ogre error
		    Ogre::ErrorDialog errorDlg;
		    errorDlg.display(e.getFullDescription());
		    return -1;
	    }
        catch (std::exception & e) {
            Ogre::ErrorDialog errorDlg;
            errorDlg.display(e.what());
            return -1;
        }
    }

	return 0;
}

// Windows special main (calls main) ==========================================

//Windows has a different entry point than normal C++ programs...
#ifdef WIN32
#include <windows.h>
#include <cstdlib>

int WINAPI WinMain(HINSTANCE thisInst, HINSTANCE prevInst, PSTR cmdLine, int nShow) {
	return main(__argc, __argv);
}
#endif //WIN32
